<?php
namespace pay;
use  think\Request;
use   think\Config;
use  think\Cache;

/**
 * Class Lian
 * @package pay 连连支付
 */
class Lian{

    private  $apiKey;
    private  $callback;
    private  $notify_url;
    public function __construct()
    {
            $class = strtolower("Lian");
            $this->Config  = $Config = Config::get($class);
            $this->apiKey = $Config['apiKey'];
            $this->mchId = $Config['mchId'];
            $this->URL = $Config['URL'];

            $this->sidRow =  Cache::get(w_g("sid"));


            $domain = Request::instance()->domain();
            //curl实例
            $this->http =new \http\Http();
        if(!empty($Config['callback_url'])){
            $this->callback = $Config['callback_url'];
        }else{
            $this->callback = $domain."/out/Notify/callbackurl";
        }
        if(!empty($Config['notify_url'])){
            $this->notify_url = $Config['notify_url'];
        }else{
            $this->notify_url =$domain."/out/Notify/handll";
        }
    }


    /**
     *  网关支付
     */
    public function byPay($deposit,$payNo,$CertName,$CertNo,$Phone){
        $baseData = $this->baseData();
        $payData = $this->payData($deposit,$payNo,$CertName,$CertNo,$Phone);//风控基本参数
        $riskItemData = $this->riskItemData($CertName,$CertNo,$Phone);//风控基本参数
        $payData = array_merge($payData,$baseData);
        $payData['risk_item'] = json_encode($riskItemData,JSON_UNESCAPED_UNICODE);
        $payData = paraFilter($payData);
        //对待签名参数数组排序
        $payData = argSort($payData);


        //生成签名结果
        $mysign = $this->buildRequestMysign($payData);
        //签名结果与签名方式加入请求提交参数组中
        $payData['sign'] = $mysign;

        $res =  $this->buildRequestForm(json_encode($payData,JSON_UNESCAPED_UNICODE));

        if(getOS()=="Linux"){

            error_log($res.PHP_EOL, 3, "/home/wwwlogs/lianlian_yuanchuang_form.log");

        }
        if(!empty($res)){

            return $res;



        }
        return false;





    }

    /**
     * 建立请求，以表单HTML形式构造（默认）
     * @param $para_temp 请求参数数组
     * @param $method 提交方式。两个值可选：post、get
     * @param $button_name 确认按钮显示文字
     * @return 提交表单HTML文本
     */
    function buildRequestForm($para, $method="post", $button_name="提交") {
        //待请求参数数组

        $sHtml = "<form id='llpaysubmit' name='llpaysubmit' action='" . $this->URL . "' method='" . $method . "'>";
        $sHtml .= "<input type='hidden' name='req_data' value='" . $para . "'/>";
        //submit按钮控件请不要含有name属性
        $sHtml = $sHtml . "<input type='submit' value='" . $button_name . "'></form>";
        $sHtml = $sHtml."<script>document.forms['llpaysubmit'].submit();</script>";
        return $sHtml;
    }





    public function payData($deposit,$payNo,$CertName,$CertNo){

        //      "sign" =>  "", //签名方式

      $data = [
          "user_id" => md5($this->sidRow['id']),//用户ID唯一标识
          "no_order" => $payNo,//商户唯一订单号
          "money_order" => $deposit,//交易金额
          "id_no" => $CertNo,//证件号码
          "acct_name" =>$CertName,//银行账号姓名
          "risk_item" => "",//风控参数
         ];
         return $data;
    }

    /**
     * 生成签名结果
     * @param $para_sort 已排序要签名的数组
     * return 签名结果字符串
     */
    public function buildRequestMysign($para_sort) {
        //把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
        $prestr = createLinkstring($para_sort);
        $mysign = "";
        //PHP5.3 版本以上 风控参数去斜杠
        $prestr =stripslashes($prestr);


        // file_put_contents("lianlian2.log",$prestr.PHP_EOL);
        //$mysign = md5Sign($prestr, $this->apiKey);
        $mysign = RsaSign($prestr, $this->apiKey);

        if(getOS()=="Linux"){
            error_log($prestr.PHP_EOL, 3, "/home/wwwlogs/lianlian_yuanchuang.log");
            error_log($mysign.PHP_EOL, 3, "/home/wwwlogs/lianlian_yuanchuang_miyao.log");

        }else{
            file_put_contents("lianlian22.log",$prestr.PHP_EOL);
        }
        return $mysign;
    }

    /**
     * 建立请求，以模拟远程HTTP的POST请求方式构造并获取连连支付的处理结果
     * @param $para_temp 请求参数数组
     * @return 连连支付处理结果
     */
    function buildRequestHttp($para_temp) {
        $sResult = '';

        //待请求参数数组字符串
        $request_data = $this->buildRequestPara($para_temp);
        //远程获取数据
        $sResult = getHttpResponsePOST($this->URL, $this->llpay_config['cacert'], $request_data, trim(strtolower($this->llpay_config['input_charset'])));
        return $sResult;
    }


    /**
     * 生成要请求给连连支付的参数数组
     * @param $para_temp 请求前的参数数组
     * @return 要请求的参数数组
     */
   public function buildRequestPara($para_temp) {
        //除去待签名参数数组中的空值和签名参数
        $para_filter = paraFilter($para_temp);
        //对待签名参数数组排序
        $para_sort = argSort($para_filter);
        //生成签名结果
        $mysign = $this->buildRequestMysign($para_sort);
        //签名结果与签名方式加入请求提交参数组中
        $para_sort['sign'] = $mysign;
        $para_sort['sign_type'] = "RSA";
        foreach ($para_sort as $key => $value) {
            $para_sort[$key] = urlencode($value);
        }
        return urldecode(json_encode($para_sort));
    }


    /**
     * 风控参数
     */
    public function riskItemData($CertName,$CertNo,$Phone){

    /*    需要传 基本参数中的，
frms_ware_category 商品类目传 2026
user_info_mercht_userno 你们平台的用户id
user_info_dt_register 用户在你们平台的注册时间
user_info_bind_phone 用户在你们平台绑定的手机号

实名类参数中的
user_info_identify_state  是否实名认证（）
user_info_identify_type 实名认证方式
user_info_full_name 用户姓名
user_info_id_no  用户身份证号*/
     $data = [
         "frms_ware_category"=>2026,
         "user_info_mercht_userno"=>$this->sidRow['id'],
         "user_info_bind_phone"=>$Phone,
         "user_info_dt_register"=>local_date('YmdHis', $this->sidRow['agoo']),
         "user_info_full_name"=>$CertName,
         "user_info_id_no"=>$CertNo,
         "user_info_identify_state"=>0,
         "user_info_identify_type"=>1,
     ];
     return $data;
    }



    public function Notify($result){

        $files = "/home/wwwlogs/controller_Notify_lianlian.log";
        $tdata = ["msg"=>"异常","status"=>0,"data"=>[]];
        $json = new \tool\Json();
        $val = $json->decode($result);
        $oid_partner = getJsonVal($val,'oid_partner' );
        $sign_type = getJsonVal($val,'sign_type' );
        $sign = getJsonVal($val,'sign' );
        $dt_order = getJsonVal($val,'dt_order' );
        $no_order = getJsonVal($val,'no_order' );
        $oid_paybill = getJsonVal($val,'oid_paybill' );
        $money_order = getJsonVal($val,'money_order' );
        $result_pay = getJsonVal($val,'result_pay' );
        $settle_date = getJsonVal($val,'settle_date' );
        $info_order = getJsonVal($val,'info_order');
        $pay_type = getJsonVal($val,'pay_type' );
        $bank_code = getJsonVal($val,'bank_code' );
        $no_agree = getJsonVal($val,'no_agree' );
        $id_type = getJsonVal($val,'id_type' );
        $id_no = getJsonVal($val,'id_no' );
        $acct_name = getJsonVal($val,'acct_name' );

        //首先对获得的商户号进行比对
        if ($oid_partner != $this->mchId) {
            if(getOS()=="Linux"){
                error_log("订单号{$no_order}，商户号异常",3,$files);
            }
            return array_merge($tdata,['status'=>0,"msg"=>"商户号异常"]);
        }
        $parameter = array (
            'oid_partner' => $oid_partner,
            'sign_type' => $sign_type,
            'dt_order' => $dt_order,
            'no_order' => $no_order,
            'oid_paybill' => $oid_paybill,
            'money_order' => $money_order,
            'result_pay' => $result_pay,
            'settle_date' => $settle_date,
            'info_order' => $info_order,
            'pay_type' => $pay_type,
            'bank_code' => $bank_code,
            'no_agree' => $no_agree,
            'id_type' => $id_type,
            'id_no' => $id_no,
            'acct_name' => $acct_name
        );
        if($result_pay !="SUCCESS"){
            if(getOS()=="Linux"){
                error_log("订单号{$no_order}已失效",3,$files);
            }
            return array_merge($tdata,['status'=>0,"msg"=>"该订单已失效"]);
        }
        if (!$this->getSignVeryfy($parameter, $sign)) {
            if(getOS()=="Linux"){
                error_log("验证签名失败".PHP_EOL,3,$files);
            }
            return array_merge($tdata,['status'=>0,"msg"=>"验证签名失败"]);
        }

        $resultBa['app_id'] =$no_order;
        $resultBa['three_app_id'] =$oid_paybill;
        $resultBa['amount'] =$money_order;

        return  ["data"=>$resultBa,"status"=>1,"msg"=>"验证成功"];

    }


    /**
     *   生成签名
     */
    public function signature($data){
        ksort($data);//字典排序
        $dataString = "";
        foreach($data as $k=>$v){
            $dataString .=$k."=".$v."&";
        }
        $stringSignTemp =  $dataString."key=".$this->apiKey;
        $md5String = strtoupper(md5($stringSignTemp));
        return $md5String;
    }


    /**
     * 获取返回时的签名验证结果
     * @param $para_temp 通知返回来的参数数组
     * @param $sign 返回的签名结果
     * @return 签名验证结果
     */
    function getSignVeryfy($para_temp, $sign) {
        //除去待签名参数数组中的空值和签名参数
        $para_filter = paraFilter($para_temp);

        //对待签名参数数组排序
        $para_sort = argSort($para_filter);

        //把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
        $prestr = createLinkstring($para_sort);

        // file_put_contents("log.txt", "原串:" . $prestr . "\n", FILE_APPEND);
        // file_put_contents("log.txt", "sign:" . $sign . "\n", FILE_APPEND);
        $isSgin = Rsaverify($prestr, $sign);
      //  $isSgin = md5Verify($prestr, $sign, $this->apiKey);

        return $isSgin;
    }


    /**
     * @return array 获取那个基本参数
     */
    private function baseData(){
       $data = [
           "oid_partner" =>  $this->mchId, //商户编号
           "app_request" => "3",//请求应用标识
           "sign_type" => "RSA", //签名方式
           "busi_partner" => "101001",//商户业务类型
           "valid_order" => "10080",//订单有效时间
           "name_goods" => "测试",//商品描述
           "info_order" => "测试",//商品描述
           "notify_url" => $this->notify_url,//商品描述
           "url_return" => $this->callback,//商品描述
           "id_type" => "0",//证件类型
           "dt_order" => local_date('YmdHis', time()),//商户业务类型
       ];
        return $data;
    }





}
?>
